/*
 * NetHeaderUtil.cpp
 *
 *  Created on: 2018年7月7日
 *      Author: zhengboyuan
 */

#include "NetHeaderUtil.h"

NetHeaderUtil::NetHeaderUtil()
{
}

NetHeaderUtil::~NetHeaderUtil()
{
}

bool NetHeaderUtil::isIP(const uint8_t* data, int size)
{
    const eth_hdr* eth = (const eth_hdr*)data;
    return (eth->eth_type == htons(ETHERTYPE_IP));
}

bool NetHeaderUtil::isTcpUdp(const uint8_t* data, int size)
{
    if (!isIP(data, size))
    {
        return false;
    }

    const eth_hdr* eth = (const eth_hdr*)data;
    data += sizeof(eth_hdr);
    size -= sizeof(eth_hdr);

    const ip_hdr* iphdr = (const ip_hdr*)data;
    data += sizeof(ip_hdr);
    size -= sizeof(ip_hdr);

    return iphdr->protocol == IP_PROTOCOL_TCP || iphdr->protocol == IP_PROTOCOL_UDP;
}

NetHeaderUtil::Protocol NetHeaderUtil::getProtocol(const uint8_t* data, int size)
{
    if (!isIP(data, size))
    {
        return kUnknown;
    }

    const eth_hdr* eth = (const eth_hdr*)data;
    data += sizeof(eth_hdr);
    size -= sizeof(eth_hdr);

    const ip_hdr* iphdr = (const ip_hdr*)data;

    if (iphdr->protocol == IP_PROTOCOL_TCP)
    {
        return kTcp;
    }

    if (iphdr->protocol == IP_PROTOCOL_UDP)
    {
        return kUdp;
    }

    return (NetHeaderUtil::Protocol)iphdr->protocol;
}

const ip_hdr* NetHeaderUtil::getIpHdr(const uint8_t* data, int size)
{
    const eth_hdr* eth = (const eth_hdr*)data;
    data += sizeof(eth_hdr);
    size -= sizeof(eth_hdr);

    if (eth->eth_type != htons(ETHERTYPE_IP))
    {
        return NULL;
    }

    const ip_hdr* iphdr = (const ip_hdr*)data;
    data += sizeof(ip_hdr);
    size -= sizeof(ip_hdr);

    return iphdr;
}

const tcp_hdr* NetHeaderUtil::getTcpHdr(const uint8_t* data, int size)
{
    NetHeaderUtil::Protocol protocol = getProtocol(data, size);
    if (protocol != kTcp)
    {
        return NULL;
    }

    const eth_hdr* eth = (const eth_hdr*)data;
    data += sizeof(eth_hdr);
    size -= sizeof(eth_hdr);

    const ip_hdr* iphdr = (const ip_hdr*)data;
    data += sizeof(ip_hdr);
    size -= sizeof(ip_hdr);

    return (const tcp_hdr*)data;
}

const udp_hdr* NetHeaderUtil::getUdpHdr(const uint8_t* data, int size)
{
    NetHeaderUtil::Protocol protocol = getProtocol(data, size);
    if (protocol != kUdp)
    {
        return NULL;
    }

    const eth_hdr* eth = (const eth_hdr*)data;
    data += sizeof(eth_hdr);
    size -= sizeof(eth_hdr);

    const ip_hdr* iphdr = (const ip_hdr*)data;
    data += sizeof(ip_hdr);
    size -= sizeof(ip_hdr);

    return (const udp_hdr*)data;
}

NetHeaderUtil::Host NetHeaderUtil::matchHost(const ip_hdr* ip, const tcp_hdr* hdr, struct sockaddr_in addr)
{
	NetHeaderUtil::Host host = matchHostPort(hdr, addr.sin_port);
	if (host == kNone)
	{
		return host;
	}

	host = matchHostIP(ip, addr.sin_addr.s_addr);
	
	return host;
}

NetHeaderUtil::Host NetHeaderUtil::matchHost(const ip_hdr* ip, const udp_hdr* hdr, struct sockaddr_in addr)
{
	NetHeaderUtil::Host host = matchHostPort(hdr, addr.sin_port);
	if (host == kNone)
	{
		return host;
	}

	host = matchHostIP(ip, addr.sin_addr.s_addr);

	return host;
}

NetHeaderUtil::Host NetHeaderUtil::matchHostPort(const tcp_hdr* hdr, uint16_t port)
{
	if (hdr->dst_port == port)
	{
		return kDst;
	}
	else if (hdr->src_port == port)
	{
		return kSrc;
	}
	
	return kNone;
}

NetHeaderUtil::Host NetHeaderUtil::matchHostPort(const udp_hdr* hdr, uint16_t port)
{
	if (hdr->src_port == port)
	{
		return kSrc;
	}
	else if (hdr->dst_port == port)
	{
		return kDst;
	}
	return kNone;
}

NetHeaderUtil::Host NetHeaderUtil::matchHostIP(const ip_hdr* hdr, uint32_t ip)
{
	if (hdr->srcaddr.s_addr == ip)
	{
		return kSrc;
	}
	else if (hdr->dstaddr.s_addr == ip)
	{
		return kDst;
	}
	return kNone;
}
